home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / etc / init.d / net.lo < prev    next >
Text File  |  2006-04-25  |  24KB  |  861 lines

  1. #!/sbin/runscript
  2. # Copyright (c) 2004-2005 Gentoo Foundation
  3. # Distributed under the terms of the GNU General Public License v2
  4. # $Header$
  5.  
  6. # Contributed by Roy Marples (uberlord@gentoo.org)
  7. # Many thanks to Aron Griffis (agriffis@gentoo.org)
  8. # for help, ideas and patches
  9.  
  10. #NB: Config is in /etc/conf.d/net
  11.  
  12. if [[ -n ${NET_DEBUG} ]]; then
  13.     set -x
  14.     devnull=/dev/stderr
  15. else
  16.     devnull=/dev/null
  17. fi
  18.  
  19. # For pcmcia users. note that pcmcia must be added to the same
  20. # runlevel as the net.* script that needs it.
  21. depend() {
  22.     use coldplug hotplug pcmcia usb isdn wlan isapnp
  23.  
  24.     # Load any custom depend functions for the given interface
  25.     # For example, br0 may need eth0 and eth1
  26.     local iface=${myservice##*.}
  27.     [[ $( type -t depend_${iface} ) == "function" ]] && depend_${iface}
  28. }
  29.  
  30. # Define where our modules are
  31. MODULES_DIR=/lib/rcscripts/net.modules.d
  32.  
  33. # Load some functions shared between ourselves and our dhcp helpers
  34. source ${MODULES_DIR}/helpers.d/functions
  35.  
  36. # Make some wrappers to fudge after/before/need/use depend flags.
  37. # These are callbacks so mods[i] will be set.
  38. after() {
  39.     local x="$*"
  40.     [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
  41.     eval "${MODULE}_after() { echo \"$x\"; }"
  42. }
  43. before() {
  44.     local x="$*"
  45.     [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
  46.     eval "${MODULE}_before() { echo \"$x\"; }"
  47. }
  48. need() {
  49.     local x="$*"
  50.     [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
  51.     eval "${MODULE}_need() { echo \"$x\"; }"
  52. }
  53. installed() {
  54.     local x="$*"
  55.     [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
  56.     # We deliberately misspell this as _installed will probably be used
  57.     # at some point
  58.     eval "${MODULE}_instlled() { echo \"$x\"; }"
  59. }
  60.  
  61. sort() {
  62.     LC_ALL=C /bin/sort "$@"
  63. }
  64.  
  65. # void module_class_wrap(char *module, char *provides)
  66. # Setup class wrappers: interface_up -> iproute2_up, for example
  67. module_class_wrap() {
  68.     local module=${1} provides=${2} x 
  69.  
  70.     # Don't wrap functions if another module already has
  71.     [[ $( type -t ${provides}_provides ) == function ]] && return
  72.  
  73.     for x in $( typeset -f | grep -o ^${module}_'[^ ]*' ); do
  74.         eval "${provides}${x#${module}}() { ${x} \"\$@\"; }"
  75.     done
  76. }
  77.  
  78. # bool module_load_minimum(char *module)
  79. #
  80. # Does the minimum checking on a module - even when forcing
  81. module_load_minimum() {
  82.     local f=${1} MODULE=${1##*/}
  83.  
  84.     if [[ ! -f ${f} ]]; then
  85.         eerror "${f} does not exist"
  86.         return 1
  87.     fi
  88.  
  89.     if ! source ${f} ; then
  90.         eerror "${MODULE} failed a sanity check"
  91.         return 1
  92.     fi
  93.  
  94.     for f in check_installed provides check_depends depend; do
  95.         [[ $( type -t ${MODULE}_${f} ) == function ]] && continue
  96.         eerror "${MODULE} does not support the required function ${f}"
  97.         return 1
  98.     done
  99.  
  100.     # Wrap our before/after/need/use functions
  101.     ${MODULE}_depend
  102.  
  103.     return 0
  104. }
  105.  
  106. # bool modules_load_auto()
  107. #
  108. # Load and check each module for sanity
  109. # If the module is not installed, the functions are to be removed
  110. modules_load_auto() {
  111.     local e f i j beforefuncs afterfuncs diffs unload
  112.  
  113.     # Populate the MODULES array
  114.     MODULES=( $( find ${MODULES_DIR}/ -maxdepth 1 -type f ! -name ".*" | sort ) )
  115.  
  116.     # Each of these sources into the global namespace, so it's
  117.     # important that module functions and variables are prefixed with
  118.     # the module name, for example iproute2_
  119.  
  120.     beforefuncs="$( typeset -F )"
  121.     j=${#MODULES[@]}
  122.     loaded_interface=false
  123.     for (( i=0; i<j; i++ )); do
  124.  
  125.         unload=false
  126.         module_load_minimum ${MODULES[i]} || unload=true
  127.         MODULES[i]=${MODULES[i]##*/}
  128.  
  129.         ! ${unload} && ${MODULES[i]}_check_installed false || unload=true
  130.  
  131.         if [[ ${MODULES[i]} == interface ]]; then
  132.             eerror "interface is a reserved name - cannot load a module called interface"
  133.             return 1
  134.         fi
  135.  
  136.         afterfuncs="$( typeset -F )"
  137.         if ${unload} ; then
  138.             unset MODULES[i]
  139.             unsetfuncs="${unsetfuncs} $( diff -U0 <( echo "${beforefuncs}" ) <( echo "${afterfuncs}" ) 2>/dev/null \
  140.                 | awk 'BEGIN { ORS = " "; } /+declare -f/ { print $3; }' )"
  141.         fi
  142.         beforefuncs="${afterfuncs}"
  143.  
  144.     done
  145.     MODULES=( "${MODULES[@]}" )
  146.  
  147.     return 0
  148. }
  149.  
  150.  
  151. # bool modules_check_installed(void)
  152. #
  153. # Ensure that all modules have the required modules loaded
  154. # This enables us to remove modules from the MODULES array
  155. # Whilst other modules can still explicitly call them
  156. # One example of this is essidnet which configures network
  157. # settings for the specific ESSID connected to as the user
  158. # may be using a daemon to configure wireless instead of our
  159. # iwconfig module
  160. modules_check_installed() {
  161.     local i j missingdeps nmods=${#MODULES[@]}
  162.  
  163.     for (( i=0; i<nmods; i++ )); do
  164.         [[ $( type -t ${MODULES[i]}_instlled ) != function ]] && continue
  165.         for j in $( ${MODULES[i]}_instlled ); do
  166.             missingdeps=true
  167.             if [[ $( type -t ${j}_check_installed ) == function ]]; then
  168.                 ${j}_check_installed && missingdeps=false
  169.             fi
  170.             ${missingdeps} && unset MODULES[i] && unset PROVIDES[i] && break
  171.         done
  172.     done
  173.  
  174.     MODULES=( "${MODULES[@]}" )
  175.     PROVIDES=( "${PROVIDES[@]}" )
  176. }
  177.  
  178. # bool modules_check_user(void)
  179. modules_check_user() {
  180.     local -a umods
  181.     local i j k l npref nmods=${#MODULES[@]}
  182.  
  183.     # Has the interface got any specific modules?
  184.     eval umods=( \"\$\{modules_${iface}\[@\]\}\" )
  185.  
  186.     # Global setting follows interface-specific setting
  187.     umods=( "${umods[@]}" "${modules[@]}" )
  188.  
  189.     # Add our preferred modules
  190.     npref=3
  191.     umods=( "${umods[@]}" "ifconfig" "dhcpcd" "iwconfig" )
  192.  
  193.     # First we strip any modules that conflict from user settings
  194.     # So if the user specifies pump then we don't use dhcpcd
  195.     for (( i=0; i<${#umods[@]}; i++ )); do
  196.         # Some users will inevitably put "dhcp" in their modules
  197.         # list.  To keep users from screwing up their system this
  198.         # way, ignore this setting so that the default dhcp
  199.         # module will be used.
  200.         [[ ${umods[i]} == dhcp ]] && continue
  201.  
  202.         # We remove any modules we explicitly don't want
  203.         if [[ ${umods[i]} == !* ]]; then
  204.             for (( j=0; j<nmods; j++ )); do
  205.                 [[ -z ${MODULES[j]} ]] && continue
  206.                 if [[ ${umods[i]:1} == ${MODULES[j]} || ${umods[i]:1} == ${PROVIDES[j]} ]]; then
  207.                     # We may need to setup a class wrapper for it even though
  208.                     # we don't use it directly
  209.                     ${MODULES[j]}_check_installed && module_class_wrap ${MODULES[j]}
  210.                     unset MODULES[j]
  211.                     unset PROVIDES[j]
  212.                     break
  213.                 fi
  214.             done
  215.             continue
  216.         fi
  217.  
  218.         if [[ $( type -t ${umods[i]}_provides ) != function ]]; then
  219.             # If the module is one of our preferred modules, then
  220.             # ignore this error; whatever is available will be
  221.             # used instead.
  222.             (( i < ${#umods[@]} - npref )) || continue
  223.             eerror "${umods[i]} is not a valid module (missing provides)"
  224.             return 1
  225.         fi
  226.  
  227.         # Ensure that the user specified module has its package installed
  228.         if (( i < ${#umods[@]} - npref )); then
  229.             # $1==true causes check_installed to report its own errors
  230.             ${umods[i]}_check_installed true || return 1
  231.         else
  232.             # If this happens on a preferred modules, ignore it;
  233.             # whatever is available will be used instead.
  234.             ${umods[i]}_check_installed false || continue
  235.         fi
  236.  
  237.         mod=$( ${umods[i]}_provides )
  238.         for (( j=0; j<nmods; j++ )); do
  239.             [[ -z ${MODULES[j]} ]] && continue
  240.             if [[ ${PROVIDES[j]} == ${mod} && ${umods[i]} != ${MODULES[j]} ]]; then
  241.                 # We don't have a match - now ensure that we still provide an alternative.
  242.                 # This is to handle our preferred modules.
  243.                 for (( l=0; l<nmods; l++ )); do
  244.                     [[ ${l} -eq ${j} || -z ${MODULES[l]} ]] && continue
  245.                     if [[ ${PROVIDES[l]} == ${mod} ]]; then
  246.                         unset MODULES[j]
  247.                         unset PROVIDES[j]
  248.                         break
  249.                     fi
  250.                 done
  251.             fi
  252.         done
  253.     done
  254.  
  255.     # Then we strip conflicting modules.
  256.     # We only need to do this for 3rd party modules that conflict with
  257.     # our own modules and the preferred list AND the user modules
  258.     # list doesn't specify a preference.
  259.     for (( i=0; i<nmods-1; i++ )); do
  260.         [[ -z ${MODULES[i]} ]] && continue            
  261.         for (( j=i+1; j<nmods; j++)); do
  262.             [[ -z ${MODULES[j]} ]] && continue
  263.             [[ ${PROVIDES[i]} == ${PROVIDES[j]} ]] && unset MODULES[j] && unset PROVIDES[j]
  264.         done
  265.     done
  266.  
  267.     MODULES=( "${MODULES[@]}" )
  268.     PROVIDES=( "${PROVIDES[@]}" )
  269.     return 0
  270. }
  271.  
  272. # void modules_sort(void)
  273.  
  274. modules_sort() {
  275.     local -a modnums sort_history modafter modbefore
  276.     local i j k p changed_something nmods=${#MODULES[@]}
  277.  
  278.     # Sort our modules
  279.     # We do this by assigning numbers to each module
  280.     # We also assign modbefore and modafter so we don't
  281.     # shell out as much because it's expensive on CPU.
  282.     modnums=()
  283.     for (( i=0; i<nmods; i++ )); do
  284.         modnums[i]=${i}
  285.         [[ $( type -t ${MODULES[i]}_after ) == function ]] && modafter[i]=$( ${MODULES[i]}_after )
  286.         [[ $( type -t ${MODULES[i]}_before ) == function ]] && modbefore[i]=$( ${MODULES[i]}_before )
  287.     done
  288.     
  289.     # Then we swap numbers based on and after/before flags
  290.     # until we don't swap anymore. The sort_history array prevents
  291.     # the possibility of an infinite loop
  292.     sort_history[0]="${modnums[*]}"
  293.     for (( k=1; 1; k++ )); do
  294.         changed_something=false
  295.         for (( i=0; i<nmods; i++ )); do
  296.             for p in ${modafter[i]}; do
  297.                 for (( j=0; j<nmods; j++ )); do
  298.                     [[ ${p} != ${MODULES[j]} && ${p} != ${PROVIDES[j]} ]] && continue
  299.                     if [[ ${modnums[i]} -lt ${modnums[j]} ]]; then
  300.                         tmp=${modnums[i]}
  301.                         modnums[i]=${modnums[j]}
  302.                         modnums[j]=${tmp}
  303.                         changed_something=true
  304.                     fi
  305.                 done
  306.             done
  307.             for p in ${modbefore[i]}; do
  308.                 for (( j=0; j<nmods; j++ )); do
  309.                     [[ ${p} != ${MODULES[j]} && ${p} != ${PROVIDES[j]} ]] && continue
  310.                     if [[ ${modnums[i]} -gt ${modnums[j]} ]]; then
  311.                         tmp=${modnums[i]}
  312.                         modnums[i]=${modnums[j]}
  313.                         modnums[j]=${tmp}
  314.                         changed_something=true
  315.                     fi
  316.                 done
  317.             done
  318.         done
  319.         ${changed_something} || break
  320.  
  321.         # Make sure we aren't repeating a previous state
  322.         # First time through, k=1, k/2=0
  323.         sort_history[k]="${modnums[*]}"
  324.         if [[ ${sort_history[k]} == ${sort_history[k/2]} ]]; then
  325.             eerror "Detected an infinite loop sorting modules; blundering ahead"
  326.             break
  327.         fi
  328.     done
  329.  
  330.     # Finally we sort our modules in number order
  331.     um=""
  332.     for (( i=0; i<nmods; i++ )); do
  333.         um="${um}${modnums[i]} ${MODULES[i]} ${PROVIDES[i]}\n"
  334.     done
  335.  
  336.     p=( $( echo -e "${um}" | sort -n | awk '{print $2,$3}' ) )
  337.     MODULES=()
  338.     PROVIDES=()
  339.     j=0
  340.     for (( i=0; i<${#p[@]}; i+=2 )); do
  341.         MODULES[j]=${p[i]}
  342.         PROVIDES[j]=${p[i+1]}
  343.         (( j++ ))
  344.     done
  345. }
  346.  
  347. # bool modules_check_depends(bool showprovides)
  348. modules_check_depends() {
  349.     local showprovides=${1:-false} nmods=${#MODULES[@]} i j needmod
  350.     local missingdeps p  interface=false
  351.  
  352.     for (( i=0; i<nmods; i++ )); do
  353.         if [[ $( type -t ${MODULES[i]}_need ) == function ]]; then
  354.             for needmod in $( ${MODULES[i]}_need ); do
  355.                 missingdeps=true
  356.                 for (( j=0; j<nmods; j++ )); do
  357.                     if [[ ${needmod} == ${MODULES[j]} || ${needmod} == ${PROVIDES[j]} ]]; then
  358.                         missingdeps=false
  359.                         break
  360.                     fi
  361.                 done
  362.                 if ${missingdeps} ; then
  363.                     eerror "${MODULES[i]} needs ${needmod} (dependency failure)"
  364.                     return 1
  365.                 fi
  366.             done
  367.         fi
  368.  
  369.         ${MODULES[i]}_check_depends || return 1
  370.         [[ ${PROVIDES[i]} == interface ]] && interface=true
  371.  
  372.         if ${showprovides} ; then
  373.             [[ ${PROVIDES[i]} != ${MODULES[i]} ]] && veinfo "${MODULES[i]} provides ${PROVIDES[i]}"
  374.         fi
  375.     done
  376.  
  377.     if ! ${interface} ; then
  378.         eerror "no interface module has been loaded"
  379.         return 1
  380.     fi
  381.  
  382.     return 0
  383. }
  384.  
  385. # bool modules_load(char *iface, bool starting)
  386. #
  387. # Loads the defined handler and modules for the interface
  388. # Returns 0 on success, otherwise 1
  389. modules_load()  {
  390.     local iface=${1} starting=${2:-true} mod p=false i j unsetfuncs
  391.     local -a x
  392.     local RC_INDENTATION=${RC_INDENTATION}    # so it will reset after function
  393.     local -a PROVIDES
  394.  
  395.     if [[ ${iface} == lo ]]; then
  396.         # We force lo to only use these modules for a major speed boost
  397.         modules_force=( "iproute2" "ifconfig" )
  398.     else
  399.         eval x=( \"\$\{modules_force_${iface}\[@\]\}\" )
  400.         [[ -n ${x} ]] && modules_force=( "${x[@]}" )
  401.         if [[ -n ${modules_force} ]]; then
  402.             ewarn "WARNING: You are forcing modules!"
  403.             ewarn "Do not complain or file bugs if things start breaking"
  404.             report=true
  405.         fi
  406.         veinfo "Loading networking modules for ${iface}"
  407.     fi
  408.     eindent
  409.  
  410.     if [[ -z ${modules_force} ]]; then
  411.         modules_load_auto || return 1
  412.     else
  413.         j=${#modules_force[@]}
  414.         for (( i=0; i<j; i++ )); do
  415.             module_load_minimum "${MODULES_DIR}/${modules_force[i]}" || return 1
  416.             ${modules_force[i]}_check_installed || unset modules_force[i]
  417.         done
  418.         MODULES=( "${modules_force[@]}" )
  419.     fi
  420.  
  421.     # We now buffer the _provides functions for a big speed boost
  422.     j=${#MODULES[@]}
  423.     for (( i=0; i<j; i++ )); do
  424.         PROVIDES[i]=$( ${MODULES[i]}_provides )
  425.     done
  426.  
  427.     if [[ -z ${modules_force[@]} ]]; then
  428.         if ${starting}; then
  429.             modules_check_user || return 1
  430.         fi
  431.  
  432.         # We unset unloaded module functions here as so we can error
  433.         # with a message informing the user to emerge the correct
  434.         # package if it's in their modules
  435.         [[ -n ${unsetfuncs} ]] && unset ${unsetfuncs}
  436.  
  437.         modules_sort
  438.     fi
  439.  
  440.     # Setup class wrappers: interface_up -> iproute2_up, for example
  441.     j=${#MODULES[@]}
  442.     for (( i=0; i<j; i++ )); do
  443.         module_class_wrap ${MODULES[i]} ${PROVIDES[i]}
  444.     done
  445.  
  446.     modules_check_installed || return 1
  447.  
  448.     [[ ${iface} != lo ]] && veinfo "modules: ${MODULES[@]}"
  449.     eindent
  450.  
  451.     [[ ${iface} != lo && ${starting} == true ]] && p=true
  452.     modules_check_depends ${p} || return 1
  453.     return 0
  454. }
  455.  
  456. # bool iface_start(char *interface)
  457. #
  458. # iface_start is called from start.  It's expected to start the base
  459. # interface (for example "eth0"), aliases (for example "eth0:1") and to start
  460. # VLAN interfaces (for example eth0.0, eth0.1).  VLAN setup is accomplished by
  461. # calling itself recursively.
  462. iface_start() {
  463.     local iface=${1} mod config_counter=-1 x warn=false config_worked=false
  464.     local RC_INDENTATION=${RC_INDENTATION}    # so it will reset after function
  465.     local -a config fallback fallback_route conf
  466.     local ifvar=$( interface_variable ${iface} )
  467.  
  468.     # pre Start any modules with
  469.     for mod in ${MODULES[@]}; do
  470.         if [[ $( type -t ${mod}_pre_start ) == function ]]; then
  471.             ${mod}_pre_start ${iface} || { eend 1; return 1; }
  472.         fi
  473.     done
  474.  
  475.     # New style config - one variable fits all
  476.     eval config=( \"\$\{config_${ifvar}\[@\]\}\" )
  477.     eval fallback=( \"\$\{fallback_${ifvar}\[@\]\}\" )
  478.     eval fallback_route=( \"\$\{fallback_route_${ifvar}\[@\]\}\" )
  479.  
  480.     # We must support old configs
  481.     if [[ -z ${config} ]]; then
  482.         interface_get_old_config ${iface} || return 1
  483.     fi
  484.  
  485.     # Handle "noop" correctly
  486.     if [[ ${config[0]} == "noop" ]]; then
  487.         if interface_is_up ${iface} true ; then
  488.             einfo "Keeping current configuration for ${iface}"
  489.             eend 0
  490.             return 0
  491.         fi
  492.  
  493.         # Remove noop from the config var
  494.         config=( "${config[@]:1}" )
  495.     fi
  496.  
  497.     # Provide a default of DHCP if no configuration is set
  498.     if [[ -z ${config} ]]; then
  499.         if [[ $( type -t dhcp_start ) == function ]]; then
  500.             config=( "dhcp" )
  501.             warn=true
  502.         else
  503.             eerror "Cannot default to dhcp as there is no dhcp module loaded"
  504.             eerror "No configuration for ${iface}"
  505.             return 1
  506.         fi
  507.     fi
  508.  
  509.     einfo "Bringing up ${iface}"
  510.     eindent
  511.     for (( config_counter=0; config_counter<${#config[@]}; config_counter++ )); do
  512.         # Handle null and noop correctly
  513.         if [[ ${config[config_counter]} == "null" \
  514.         || ${config[config_counter]} == "noop" ]]; then
  515.             eend 0
  516.             config_worked=true
  517.             continue
  518.         fi
  519.  
  520.         if ${warn}; then
  521.             ewarn "Configuration not set for ${iface} - assuming dhcp"
  522.             warn=false
  523.         fi
  524.  
  525.         # We convert it to an array - this has the added
  526.         # bonus of trimming spaces!
  527.         conf=( ${config[config_counter]} )
  528.         einfo "${conf[0]}"
  529.  
  530.         # Do we have a function for our config?
  531.         if [[ $( type -t ${conf[0]}_start ) == function ]]; then
  532.             # Check that the module is valid
  533.             x=false
  534.             for mod in ${MODULES[@]}; do
  535.                 if [[ $( ${mod}_provides ) == ${conf[0]} ]]; then
  536.                     x=true
  537.                     break
  538.                 fi
  539.             done
  540.  
  541.             if ! ${x}; then
  542.                 [[ $( type -t ${conf[0]}_check_installed == function ) ]] && ${conf[0]}_check_installed true
  543.                 eerror "No loaded modules provide \"${conf[0]}\" (${conf[0]}_start)"
  544.             else
  545.                 eindent
  546.                 ${conf[0]}_start ${iface} ; x=$?
  547.                 eoutdent
  548.                 [[ ${x} == 0 ]] && config_worked=true && continue
  549.             fi
  550.         # We need to test to see if it's an IP address or a function
  551.         # We do this by testing if the 1st character is a digit
  552.         elif [[ ${conf[0]:0:1} == [[:digit:]] || ${conf[0]} == *:* ]]; then
  553.             x=0
  554. #            if [[ $(type -t address_exists ) == function ]]; then
  555. #                if address_exists ${iface} ${conf[0]} ; then
  556. #                    eerror "${conf[0]%%/*} already taken on ${iface}"
  557. #                    x=1
  558. #                fi
  559. #            fi
  560.             [[ ${x} == 0 ]] && interface_add_address ${iface} ${conf[@]} ; x=$?
  561.             eend ${x} && config_worked=true && continue
  562.         else
  563.             eerror "No loaded modules provide \"${conf[0]}\" (${conf[0]}_start)"
  564.         fi
  565.  
  566.         if [[ -n ${fallback[config_counter]} ]]; then
  567.             einfo "Trying fallback configuration"
  568.             config[config_counter]=${fallback[config_counter]}
  569.             fallback[config_counter]=''
  570.  
  571.             # Do we have a fallback route?
  572.             if [[ -n ${fallback_route[config_counter]} ]]; then
  573.                 eval "routes_${ifvar}=( "\"\$\{fallback_route\[${config_counter}\]\[@\]\}\"" )"
  574.                 fallback_route[config_counter]=''
  575.             fi
  576.  
  577.             (( config_counter-- )) # since the loop will increment it
  578.             continue
  579.         fi
  580.     done
  581.     eoutdent
  582.  
  583.     # We return failure if no configuration parameters worked
  584.     ${config_worked} || return 1
  585.  
  586.     # Start any modules with _post_start
  587.     for mod in ${MODULES[@]}; do
  588.         if [[ function == $( type -t ${mod}_post_start ) ]]; then
  589.             ${mod}_post_start ${iface} || return 1
  590.         fi
  591.     done
  592.  
  593.     return 0
  594. }
  595.  
  596. # bool iface_stop(char *interface)
  597. #
  598. # iface_stop: bring down an interface.  Don't trust information in
  599. # /etc/conf.d/net since the configuration might have changed since
  600. # iface_start ran.  Instead query for current configuration and bring
  601. # down the interface.
  602. #
  603. # However, we are currently reliant on handler and modules specified
  604. # in /etc/conf.d/net
  605. iface_stop() {
  606.     local iface=${1} i aliases need_begin=false mod
  607.     local RC_INDENTATION=${RC_INDENTATION}    # so it will reset after function
  608.  
  609.     # pre Stop any modules
  610.     for mod in ${MODULES[@]}; do
  611.         [[ $( type -t ${mod}_pre_stop ) == function ]] && ${mod}_pre_stop ${iface}
  612.     done
  613.  
  614.     einfo "Bringing down ${iface}"
  615.     eindent
  616.  
  617.     # Collect list of aliases for this interface.
  618.     # List will be in reverse order.
  619.     aliases=$( interface_get_aliases_rev ${iface} )
  620.  
  621.     # Stop aliases before primary interface.
  622.     # Note this must be done in reverse order, since ifconfig eth0:1 
  623.     # will remove eth0:2, etc.  It might be sufficient to simply remove 
  624.     # the base interface but we're being safe here.
  625.     for i in ${aliases} ${iface}; do
  626.         # Stop all our modules
  627.         for mod in ${MODULES[@]}; do
  628.             [[ $( type -t ${mod}_stop ) == function ]] && ${mod}_stop ${i}
  629.         done
  630.  
  631.         # A module may have removed the interface
  632.         interface_exists ${iface} || { eend 0; continue; }
  633.  
  634.         # Delete all the addresses for this alias
  635.         interface_del_addresses ${i}
  636.  
  637.         # Do final shut down of this alias
  638.         ebegin "Shutting down ${i}"
  639.         interface_iface_stop ${i}
  640.         eend $?
  641.     done
  642.  
  643.     # post Stop any modules
  644.     for mod in ${MODULES[@]}; do
  645.         # We have already taken down the interface, so no need to error
  646.         [[ $( type -t ${mod}_post_stop ) == function ]] && ${mod}_post_stop ${iface}
  647.     done
  648.  
  649.     return 0
  650. }
  651.  
  652. # bool run_start(char *iface)
  653. #
  654. # Brings up ${IFACE}.  Calls preup, iface_start, then postup.
  655. # Returns 0 (success) unless preup or iface_start returns 1 (failure).
  656. # Ignores the return value from postup.
  657. # We cannot check that the device exists ourselves as modules like
  658. # tuntap make create it.
  659. run_start() {
  660.     local iface=${1} ifvar x
  661.  
  662.     if [[ ${iface} == lo ]]; then
  663.         ebegin "Bringing up ${iface}"
  664.         interface_loopback_create
  665.         eend $?
  666.         return $?
  667.     fi
  668.  
  669.     # We may not have a loaded module for ${iface}
  670.     # Some users may have "alias natsemi eth0" in /etc/modules.d/foo
  671.     # so we can work with this
  672.     # However, if they do the same with eth1 and try to start it
  673.     # but eth0 has not been loaded then the module gets loaded as
  674.     # eth0.
  675.     # Not much we can do about this :(
  676.     # Also, we cannot error here as some modules - such as bridge
  677.     # create interfaces
  678.     if ! interface_exists ${iface} ; then
  679.         /sbin/modprobe ${iface} &>/dev/null
  680.     fi
  681.  
  682.     # Setup variables for pre/post to use
  683.     ifvar=$( interface_variable ${iface} )
  684.     local IFACE=${iface} IFVAR=${ifvar}
  685.  
  686.     # Call user-defined preup function if it exists
  687.     if [[ $( type -t preup ) == function ]]; then
  688.         einfo "Running preup function"
  689.         eindent
  690.         preup ${iface} ; x=$?
  691.         eoutdent
  692.         if [[ ${x} != 0 ]]; then
  693.             eerror "preup ${iface} failed"
  694.             return 1
  695.         fi
  696.     fi
  697.  
  698.     # Don't let preup modify us
  699.     iface=${1}
  700.     local IFACE=${iface} IFVAR=${ifvar} config
  701.  
  702.     # If config is set to noop and the interface is up with an address
  703.     # then we don't start it
  704.     eval config=( \"\$\{config_${ifvar}\[@\]\}\" )
  705.     if [[ ${config[0]} == "noop" ]] && interface_is_up ${iface} true ; then
  706.         einfo "Keeping current configuration for ${iface}"
  707.         eend 0
  708.     else
  709.         # Remove noop from the config var
  710.         [[ ${config[0]} == "noop" ]] && eval "config_${ifvar}=( "\"\$\{config\[@\]:1\}\"" )"
  711.  
  712.         # There may be existing ip address info - so we strip it
  713.         interface_del_addresses ${iface}
  714.  
  715.         # Start the interface
  716.         if ! iface_start ${iface} ; then
  717.             interface_exists ${iface} && interface_down ${iface}
  718.             eend 1
  719.             return 1
  720.         fi
  721.     fi
  722.  
  723.     # Call user-defined postup function if it exists
  724.     if [[ $( type -t postup ) == function ]]; then
  725.         einfo "Running postup function"
  726.         eindent
  727.         postup ${iface}
  728.         eoutdent
  729.     fi
  730.  
  731.     return 0
  732. }
  733.  
  734. # bool run_stop(char *iface) {
  735. #
  736. # Brings down ${iface}.  If predown call returns non-zero, then
  737. # stop returns non-zero to indicate failure bringing down device.
  738. # In all other cases stop returns 0 to indicate success.
  739. run_stop() {
  740.     local iface=${1} ifvar x
  741.  
  742.     # Don't run any special shutdown functions for lo
  743.     if [[ ${iface} == lo ]]; then
  744.         ebegin "Shutting down ${iface}"
  745.         interface_iface_stop ${iface}
  746.         eend $?
  747.         return 0
  748.     fi
  749.  
  750.     # Setup variables for pre/post to use
  751.     ifvar=$( interface_variable ${iface} )
  752.     local IFACE=${iface} IFVAR=${ifvar}
  753.  
  754.     # Call user-defined predown function if it exists
  755.     if [[ $( type -t predown ) == function ]]; then
  756.         einfo "Running predown function"
  757.         eindent
  758.         predown ${iface} ; x=$?
  759.         eoutdent
  760.         if [[ ${x} != 0 ]]; then
  761.             eend 1 "predown ${iface} failed"
  762.             return 1
  763.         fi
  764.     elif is_net_fs /; then
  765.         eerror "root filesystem is network mounted -- can't stop ${iface}"
  766.         return 1
  767.     fi
  768.  
  769.     # Don't let predown modify us
  770.     iface=${1}
  771.     local IFACE=${iface} IFVAR=${ifvar}
  772.  
  773.     iface_stop ${iface} || return 1  # always succeeds, btw
  774.  
  775.     # Call user-defined postdown function if it exists
  776.     if [[ $( type -t postdown ) == function ]]; then
  777.         einfo "Running postdown function"
  778.         eindent
  779.         postdown ${iface}
  780.         eoutdent
  781.     fi
  782.  
  783.     return 0
  784. }
  785.  
  786. # bool run(char *iface, char *cmd)
  787. #
  788. # Main start/stop entry point
  789. # We load modules here and remove any functions that they
  790. # added as we may be called inside the same shell scope for another interface
  791. run() {
  792.     local iface=${1} cmd=${2} r=1 RC_INDENTATION=${RC_INDENTATION}    # so it will reset after function
  793.     local before starting=true
  794.     local -a MODULES mods
  795.  
  796.     # We need to override the exit function as runscript.sh now checks
  797.     # for it. We need it so we can mark the service as inactive ourselves.
  798.     unset -f exit
  799.  
  800.     eindent
  801.  
  802.     unset_functions=${unset_functions:-false}
  803.     ${unset_functions} && before="$( typeset -F )"
  804.     [[ ${cmd} == "stop" ]] && starting=false
  805.     if modules_load ${iface} ${starting} ; then
  806.         if [[ ${cmd} == "stop" ]]; then
  807.             # Reverse the module list for stopping
  808.             mods=( "${MODULES[@]}" )
  809.             for ((i = 0; i < ${#mods[@]}; i++)); do
  810.                 MODULES[i]=${mods[((${#mods[@]} - i - 1))]}
  811.             done
  812.  
  813.             run_stop ${iface} && r=0
  814.         else
  815.             run_start ${iface} && r=0
  816.         fi
  817.     fi
  818.  
  819.     # We need to remove added functions before we quit as other init
  820.     # scripts may be launching afterwards
  821.     ${unset_functions} && \
  822.     unset $( diff -U0 <( echo "${before}" ) <( echo "$( typeset -F )" ) 2>/dev/null \
  823.         | awk 'BEGIN { ORS = " "; } /+declare -f/ { print $3; }' ) 2>/dev/null
  824.  
  825.     return ${r}
  826. }
  827.  
  828. # bool start(void)
  829. #
  830. # Start entry point so that we only have one function
  831. # which localises variables and unsets functions
  832. start() {
  833.     einfo "Starting ${IFACE}"
  834.     run ${IFACE} start
  835.     return $?
  836. }
  837.  
  838. # bool stop(void)
  839. #
  840. # Stop entry point so that we only have one function
  841. # which localises variables and unsets functions
  842. stop() {
  843.     einfo "Stopping ${IFACE}"
  844.     run ${IFACE} stop
  845.     return $?
  846. }
  847.  
  848. # bool restart(void)
  849. #
  850. # Restart entry point
  851. # We do this so as we only have to remove functions when stopping
  852. restart() {
  853.     local unset_functions=true
  854.     service_started "${myservice}" && svc_stop
  855.     unset_functions=false
  856.     svc_start
  857.     return $?
  858. }
  859.  
  860. # vim:ts=4
  861.